package modelo.persistencia;

import java.io.IOException;
import java.util.ArrayList;
import modelo.dominio.Cliente;
import modelo.dominio.Motorista;
import modelo.dominio.Locacao;
import modelo.dominio.TipoLocacao;
import modelo.dominio.Veiculo;
import modelo.dominio.TipoVeiculo;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.util.Calendar;
import java.util.GregorianCalendar;

import java.text.SimpleDateFormat;
import javax.persistence.EntityManager;
import javax.persistence.Query;

public class PersistenciaLocacao extends DAOBase {
	
	private ArrayList<Locacao> listaLocacoes = new ArrayList<Locacao>();
	
	public ArrayList<Locacao> getListaLocacoes() {
		EntityManager em = getEntityManager();
		Query query = em.createQuery("from Locacao");
		listaLocacoes = (ArrayList<Locacao>)query.getResultList();
		return listaLocacoes;
	}
	
	public ArrayList<Locacao> getLocacoesEmAberto() {
		ArrayList<Locacao> locacoesEmAberto = new ArrayList<Locacao>();
		EntityManager em = getEntityManager();
		Query query = em.createQuery("from Locacao as locacao where locacao.finalizada = false");
		locacoesEmAberto = (ArrayList<Locacao>)query.getResultList();
		return locacoesEmAberto;
	}
	
	public ArrayList<Locacao> getLocacoesFinalizadas() {
		ArrayList<Locacao> locacoesFinalizadas = new ArrayList<Locacao>();
		EntityManager em = getEntityManager();
		Query query = em.createQuery("from Locacao as locacao where locacao.finalizada = true");
		locacoesFinalizadas = (ArrayList<Locacao>)query.getResultList();
		return locacoesFinalizadas;
	}

	public ArrayList<Locacao> consultarLocacaoCliente(Locacao locacao) {
		ArrayList<Locacao> locacoesDoCliente = new ArrayList<Locacao>();
		EntityManager em = getEntityManager();
		long cpf = locacao.getCliente().getCpf();
		Query query = em.createQuery("from Locacao as locacao where locacao.cliente.cpf = " + cpf);
		locacoesDoCliente = (ArrayList<Locacao>)query.getResultList();
		return locacoesDoCliente;
	}
	
	public Locacao consultarLocacaoVeiculo(Locacao locacao) {
		Locacao resultado;
		EntityManager em = getEntityManager();
		String placa = locacao.getVeiculo().getPlaca();
		Query query = em.createQuery("from Locacao as l where l.finalizada = false and l.veiculo.placa = '"+placa+"'");
		resultado = (Locacao)query.getSingleResult();
		return resultado;
	}
	
	public double calcularValorLocacoes(){
		double total = 0;
		EntityManager em = getEntityManager();
		Query query = em.createQuery("select sum(valorLocacoes) from Locacao");
		total = (Double)query.getSingleResult();
		return total;
	}
	
	// Calcula a receita esperada das locações em aberto
	public double calculaReceitaEsperada(ArrayList<Locacao> locacoes){
		double total = 0;
		PersistenciaVeiculo persistenciaVeiculo = new PersistenciaVeiculo();
		for (int i = 0; i < locacoes.size(); i++) {
			Veiculo veiculo = new Veiculo();
			retornaLocacao(locacoes.get(i));
			total += locacoes.get(i).getValorLocacao();
		}
		return total;
	}
	
	// Gravação da locação em arquivo
	public void salvarEmArquivo(ArrayList<Locacao> locacoes) throws IOException{
		int i;
		BufferedWriter writer = new BufferedWriter(new FileWriter("locacoes.txt"));
		PrintWriter output = new PrintWriter(writer);
		
		for (i = 0; i < locacoes.size(); i++) { 
			output.println (locacoes.get(i).getIdLocacao() + ";"
			+ locacoes.get(i).getQuilometragemSaida() + ";"
			+ locacoes.get(i).getQuilometragemEntrada() + ";"
			+ locacoes.get(i).getDataSaida().getTimeInMillis() + ";"
			+ locacoes.get(i).getDataDevolucao().getTimeInMillis() + ";"
			+ locacoes.get(i).getValorLocacao() + ";" 
			+ locacoes.get(i).getPrevisaoDias() + ";"
			+ locacoes.get(i).isFinalizada() + ";"
			+ locacoes.get(i).getTipoLocacao().getIdTipoLocacao() + ";"	//grava o id do TipoLocacao
			+ locacoes.get(i).getMotorista().getCnh() + ";"			//grava a placa do Veiculo
			+ locacoes.get(i).getCliente().getCpf()	+ ";"			//grava o CPF do Cliente
			+ locacoes.get(i).getVeiculo().getPlaca());
		}
		writer.close();
		output.close();
	}

	
	// Leitura do arquivo
	public void lerArquivo(ArrayList<Locacao> locacoes) throws IOException{
		int idLocacao, previsaoDias;
		long quilometragemSaida, quilometragemEntrada, aux;
		Calendar dataSaida, dataDevolucao;
		double valorLocacao;
		boolean status;
		dataSaida = new GregorianCalendar();
		dataDevolucao = new GregorianCalendar();;
		File arquivo = new File("locacoes.txt");
		if(!arquivo.exists()){
			arquivo.createNewFile();
		}
		else {
			FileReader reader = new FileReader("locacoes.txt");
			BufferedReader leitor = new BufferedReader(reader);
				
			String linha = null;
			String [] vetor = null;

			while((linha = leitor.readLine()) != null) {
				vetor = linha.split(";");
				idLocacao = Integer.parseInt(vetor[0]);
				quilometragemSaida = Long.parseLong(vetor[1]);
				quilometragemEntrada = Long.parseLong(vetor[2]);
				aux = Long.parseLong(vetor[3]);
				dataSaida.setTimeInMillis(aux);
				aux = Long.parseLong(vetor[4]);
				dataDevolucao.setTimeInMillis(aux);
				valorLocacao = Double.parseDouble(vetor[5]);
				previsaoDias = Integer.parseInt(vetor[6]);
				status = Boolean.parseBoolean(vetor[7]);
				TipoLocacao tipoLocacao = new TipoLocacao(Integer.parseInt(vetor[8]));
				Motorista motorista = new Motorista(vetor[9]);
				Cliente cliente = new Cliente(vetor[10]);
				Veiculo veiculo = new Veiculo(vetor[11]);
				
				Locacao novaLocacao = new Locacao(idLocacao, quilometragemSaida,
					quilometragemEntrada, dataSaida, dataDevolucao, valorLocacao,
					previsaoDias, status, tipoLocacao, motorista, cliente, veiculo);		
			}
			leitor.close();
			reader.close();
		}
	}
	
	// Converte uma string para um objeto GregorianCalendar
	public GregorianCalendar converteData(String data){
		GregorianCalendar dataRetorno = new GregorianCalendar();
		try {
			SimpleDateFormat formatoData = new SimpleDateFormat("dd/MM/yyyy");
			dataRetorno.getInstance();
			dataRetorno.setTime(formatoData.parse(data));
		} catch (Exception e) {}
		return dataRetorno;
	}
	
	// Cálculo da diferença em dias entre data de saída e a data de devolução
	public int calculaDiasDiferenca(Locacao locacao){
		long diferenca = locacao.getDataDevolucao().getTimeInMillis() -
		locacao.getDataSaida().getTimeInMillis();
		// Quantidade de milissegundos em um dia
		int tempoDia = 1000 * 60 * 60 * 24;
		int diasDiferenca = (int)diferenca / tempoDia;
		return diasDiferenca + 1;
	}
	
	// Retorna a locação com todos os seus atributos preenchidos
	public void retornaLocacao(Locacao locacao){
		int idTipoVeiculo, idTipoLocacao;
		
		PersistenciaCliente persistenciaCliente = new PersistenciaCliente();
		PersistenciaMotorista persistenciaMotorista = new PersistenciaMotorista();
		PersistenciaVeiculo persistenciaVeiculo = new PersistenciaVeiculo();
		PersistenciaTipoVeiculo persistenciaTipoVeiculo = new PersistenciaTipoVeiculo();
		PersistenciaTipoLocacao persistenciaTipoLocacao = new PersistenciaTipoLocacao();
		
		idTipoVeiculo = locacao.getVeiculo().getTipoVeiculo().getIdTipoVeiculo();
		idTipoLocacao = locacao.getTipoLocacao().getIdTipoLocacao();
		Cliente clientePesquisa = new Cliente(locacao.getCliente().getCpf());
		Motorista motoristaPesquisa = new Motorista(locacao.getMotorista().getCnh());
		Veiculo veiculoPesquisa = new Veiculo(locacao.getVeiculo().getPlaca());
		TipoVeiculo tipoVeiculoPesquisa = new TipoVeiculo(idTipoVeiculo);
		TipoLocacao tipoLocacaoPesquisa = new TipoLocacao(idTipoLocacao);
		
		Cliente cliente = new Cliente();
		Motorista motorista = new Motorista();
		Veiculo veiculo = new Veiculo();
		TipoVeiculo tipoVeiculo = new TipoVeiculo();
		TipoLocacao tipoLocacao = new TipoLocacao();
		
		cliente = (Cliente)persistenciaCliente.consultar(clientePesquisa);
		motorista = persistenciaMotorista.consultarMotoristaCNH(motoristaPesquisa);
		tipoVeiculo = (TipoVeiculo)persistenciaTipoVeiculo.consultar(tipoVeiculoPesquisa);
		veiculo = (Veiculo)persistenciaVeiculo.consultar(veiculoPesquisa);
		veiculo.setTipoVeiculo(tipoVeiculo);
		tipoLocacao = (TipoLocacao)persistenciaTipoLocacao.consultar(tipoLocacaoPesquisa);
		locacao.setCliente(cliente);
		locacao.setMotorista(motorista);
		locacao.setVeiculo(veiculo);
		locacao.setTipoLocacao(tipoLocacao);
	}
	
}
